from typing import List, Optional, Dict, Any
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, or_, and_
from fastapi import HTTPException, status

from modules.system.models.data_permission import SysDataPermissionRule, SysRoleDataPermission
from modules.system.schemas.data_permission_schemas import (
    DataPermissionRuleCreate,
    DataPermissionRuleUpdate,
    RoleDataPermissionCreate,
    RoleDataPermissionBatchCreate
)

from core.pagination import paging_data, _CustomPageParams
from utils.query_builder import build_select_stmt
from modules.system.curd.data_permission_rule_curd import data_permission_rule_dao
from modules.system.curd.role_data_permission_curd import role_data_permission_dao


class DataPermissionRuleService:
    """数据权限规则服务类"""
    
    @staticmethod
    async def get_rule_by_id(db: AsyncSession, rule_id: int) -> Optional[SysDataPermissionRule]:
        """根据ID获取数据权限规则"""
        return await data_permission_rule_dao.get_by_id(db, rule_id)
    
    @staticmethod
    async def get_by_rule_code(db: AsyncSession, rule_code: str) -> Optional[SysDataPermissionRule]:
        """根据规则编码获取数据权限规则"""
        return await data_permission_rule_dao.get_by_rule_code(db, rule_code)
    
    @staticmethod
    async def get_by_table_name(db: AsyncSession, table_name: str) -> List[SysDataPermissionRule]:
        """根据表名获取数据权限规则列表"""
        return await data_permission_rule_dao.get_by_table_name(db, table_name)
    
    @staticmethod
    async def check_rule_code_exists(db: AsyncSession, rule_code: str, exclude_id: Optional[int] = None) -> bool:
        """检查规则编码是否已存在"""
        return await data_permission_rule_dao.check_rule_code_exists(db, rule_code, exclude_id)
    
    @staticmethod
    async def get_active_rules(db: AsyncSession) -> List[SysDataPermissionRule]:
        """获取所有启用的数据权限规则"""
        return await data_permission_rule_dao.get_active_rules(db)
    
    @staticmethod
    async def get_rules_with_pagination(db: AsyncSession, query_params) -> Dict[str, Any]:
        """获取数据权限规则列表（分页）"""
        stmt = build_select_stmt(SysDataPermissionRule, query_params)
        params = _CustomPageParams(page=query_params.page, size=query_params.size)
        return await paging_data(db, stmt, params=params)
    
    @staticmethod
    async def create_rule(db: AsyncSession, payload: DataPermissionRuleCreate) -> SysDataPermissionRule:
        """创建数据权限规则"""
        # 检查规则编码是否已存在
        if await DataPermissionRuleService.check_rule_code_exists(db, payload.rule_code):
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="规则编码已存在")
        rule = await data_permission_rule_dao.create(db, payload)
        await db.commit()
        await db.refresh(rule)
        return rule
    
    @staticmethod
    async def update_rule(db: AsyncSession, rule_id: int, payload: DataPermissionRuleUpdate) -> SysDataPermissionRule:
        """更新数据权限规则"""
        rule = await DataPermissionRuleService.get_rule_by_id(db, rule_id)
        if not rule:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="数据权限规则不存在")

        # 检查规则编码唯一性
        if payload.rule_code and payload.rule_code != rule.rule_code:
            if await DataPermissionRuleService.check_rule_code_exists(db, payload.rule_code, rule_id):
                raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="规则编码已存在")

        updated = await data_permission_rule_dao.update(db, rule_id, payload)
        await db.commit()
        # 更新后返回最新记录
        return updated  # 已由仓储层 select_model 返回最新记录
    
    @staticmethod
    async def delete_rule(db: AsyncSession, rule_id: int) -> None:
        """删除数据权限规则"""
        rule = await DataPermissionRuleService.get_rule_by_id(db, rule_id)
        if not rule:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="数据权限规则不存在")

        # 先删除相关的角色权限关联
        await RoleDataPermissionService.delete_by_rule_id(db, rule_id)

        await data_permission_rule_dao.delete(db, rule_id)
        await db.commit()


class RoleDataPermissionService:
    """角色数据权限关联服务类"""
    
    @staticmethod
    async def get_by_role_id(db: AsyncSession, role_id: int) -> List[SysRoleDataPermission]:
        """根据角色ID获取数据权限关联列表"""
        return await role_data_permission_dao.get_by_role_id(db, role_id)
    
    @staticmethod
    async def get_by_rule_id(db: AsyncSession, rule_id: int) -> List[SysRoleDataPermission]:
        """根据规则ID获取数据权限关联列表"""
        return await role_data_permission_dao.get_by_rule_id(db, rule_id)
    
    @staticmethod
    async def get_role_rules(db: AsyncSession, role_ids: List[int]) -> List[SysDataPermissionRule]:
        """获取多个角色关联的数据权限规则列表"""
        return await role_data_permission_dao.get_role_rules(db, role_ids)
    
    @staticmethod
    async def create_role_permission(db: AsyncSession, data: RoleDataPermissionCreate) -> SysRoleDataPermission:
        """创建角色数据权限关联"""
        permission = await role_data_permission_dao.create(db, data)
        await db.commit()
        await db.refresh(permission)
        return permission
    
    @staticmethod
    async def batch_create_role_permissions(db: AsyncSession, data: RoleDataPermissionBatchCreate) -> List[SysRoleDataPermission]:
        """批量创建角色数据权限关联"""
        # 先删除该角色的所有数据权限关联
        await role_data_permission_dao.delete_by_role_id(db, data.role_id)

        # 批量创建新的关联
        permissions: List[SysRoleDataPermission] = []
        for rule_id in data.rule_ids:
            permission = await role_data_permission_dao.create(
                db,
                RoleDataPermissionCreate(role_id=data.role_id, rule_id=rule_id, status=data.status),
            )
            permissions.append(permission)

        await db.commit()
        for permission in permissions:
            await db.refresh(permission)
        return permissions
    
    @staticmethod
    async def delete_role_permissions(db: AsyncSession, role_id: int) -> bool:
        """删除角色的所有数据权限关联"""
        try:
            await role_data_permission_dao.delete_by_role_id(db, role_id)
            await db.commit()
            return True
        except Exception:
            await db.rollback()
            return False
    
    @staticmethod
    async def delete_role_permission(db: AsyncSession, permission_id: int) -> bool:
        """删除单个角色数据权限关联"""
        try:
            await role_data_permission_dao.delete_by_id(db, permission_id)
            await db.commit()
            return True
        except Exception:
            await db.rollback()
            return False
    
    @staticmethod
    async def delete_by_role_id(db: AsyncSession, role_id: int) -> bool:
        """删除角色的所有数据权限关联"""
        try:
            await role_data_permission_dao.delete_by_role_id(db, role_id)
            await db.commit()
            return True
        except Exception:
            await db.rollback()
            return False
    
    @staticmethod
    async def delete_by_rule_id(db: AsyncSession, rule_id: int) -> bool:
        """删除规则的所有数据权限关联"""
        try:
            await role_data_permission_dao.delete_by_rule_id(db, rule_id)
            await db.commit()
            return True
        except Exception:
            await db.rollback()
            return False